package com.sec.etech.ism.controller;

import com.alibaba.fastjson.JSONObject;
import com.sec.etech.employeesync.sapquery.factory.QueryStrategyFactory;
import com.sec.etech.employeesync.sapquery.service.SapEmployeeQueryService;
import com.sec.etech.employeesync.sapquery.strategy.QueryStrategy;
import com.sec.etech.employeesync.schedule.SyncSapEmployeeScheduled;
import com.sec.etech.ism.model.IsmAppSetting;
import com.sec.etech.ism.service.IsmAppSettingService;
import com.sec.etech.ism.service.IsmService;
import com.sec.etech.ism.service.IsmSyncPartsSapNumService;
import com.sec.etech.ism.service.MaterialNoLogService;
import com.sec.etech.ism.util.SapSignatureUtil;
import lombok.extern.slf4j.Slf4j;
import org.openbpm.base.api.aop.annotion.CatchErr;
import org.openbpm.base.api.response.impl.ResultMsg;
import org.openbpm.base.rest.ControllerTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;


@RestController
@RequestMapping("/ism")
@Slf4j
public class IsmController extends ControllerTools {
    @Resource
    IsmService ismService;
    @Resource
    MaterialNoLogService materialNoLogService;
    @Resource
    IsmSyncPartsSapNumService ismSyncPartsSapNumService;
    @Resource
    private SyncSapEmployeeScheduled syncSapEmployeeScheduled;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private SapEmployeeQueryService sapEmployeeQueryService;
    @Autowired
    private IsmAppSettingService ismAppSettingService;

    @RequestMapping(value = "/signature", method = {RequestMethod.POST})
    @CatchErr("签名失败")
    public ResultMsg signature(@RequestBody JSONObject object) throws Exception {
        if (object.getJSONObject("input_params") == null || object.getString("appSecrete") == null) {
            return getWarnResult("接口调用失败：缺少input_params、appSecrete参数！");
        }
        JSONObject resObject = ismService.signature(object.getJSONObject("input_params"), object.getString("appSecrete"));
        return getSuccessResult(resObject);
    }

    @RequestMapping(value = "/call/byTaskId", method = {RequestMethod.GET, RequestMethod.POST})
    @CatchErr("使用任务ID重新发起接口请求失败")
    public ResultMsg callByTaskId(@RequestParam Long taskId) throws Exception {
        String res = ismService.callByTaskId(taskId);
        return "success".equals(res) ? getSuccessResult() : getWarnResult(res);
    }

    @PostMapping(value = "/beCall/{sysCode}/proc/{methodName}")
    @CatchErr("proc服务分类发起接口请求失败")
    public ResultMsg beCallProc(@PathVariable String sysCode, @PathVariable String methodName, @RequestBody String params) {
        return this.beCall(sysCode, methodName, params);
    }

    @PostMapping(value = "/beCall/{sysCode}/prod/{methodName}")
    @CatchErr("prod服务分类发起接口请求失败")
    public ResultMsg beCallProd(@PathVariable String sysCode, @PathVariable String methodName, @RequestBody String params) {
        return this.beCall(sysCode, methodName, params);
    }

    @PostMapping(value = "/beCall/{sysCode}/pre/{methodName}")
    @CatchErr("pre服务分类发起接口请求失败")
    public ResultMsg beCallPre(@PathVariable String sysCode, @PathVariable String methodName, @RequestBody String params) {
        return this.beCall(sysCode, methodName, params);
    }

    @PostMapping(value = "/beCall/{sysCode}/proj/{methodName}")
    @CatchErr("proj服务分类发起接口请求失败")
    public ResultMsg beCallProj(@PathVariable String sysCode, @PathVariable String methodName, @RequestBody String params) {
        return this.beCall(sysCode, methodName, params);
    }

    @PostMapping(value = "/call/{sysCode}/{serviceCode}")
    @CatchErr("调用第三方系统接口失败")
    public ResultMsg callOther(@PathVariable String sysCode, @PathVariable String serviceCode, @RequestBody JSONObject object) {
        if (!serviceCode.equals(object.getString("serviceCode"))) {
            return getWarnResult("无此接口，如需定制请联系ETech相关人员！");
        }
        try {
            JSONObject resObj = ismService.call3rdService(sysCode, serviceCode, object.getJSONObject("businessParams"));
            if ("success".equals(resObj.getString("flag"))) {
                return getSuccessResult(resObj.get("data"));
            } else {
                return getWarnResult(resObj.getString("msg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return getWarnResult(e.getMessage() != null ? e.getMessage() : "接口调用异常请联系Etech管理员处理！");
        }
    }

    @RequestMapping(value = "/employeesync")
    @CatchErr
    public ResultMsg employeesync(@RequestParam String option,
                                  @RequestParam String code,
                                  @RequestParam String currentUserId,
                                  @RequestParam(required = false) String account) {

        JSONObject businessParams = new JSONObject();
        businessParams.put("option", option);
        businessParams.put("currentUserId", currentUserId);

        if ("company".equals(option)) {
            businessParams.put("code", code.split(",")); // 将 code 转换为数组
            businessParams.put("type", "COMPANY"); // 将 code 转换为数组
        } else if ("account".equals(option)) {
            businessParams.put("code", code);
            businessParams.put("account", account);
            businessParams.put("type", "SINGLE"); // 将 code 转换为数组
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessParams", businessParams);
        jsonObject.put("serviceCode", "querySapEmployeeByWerks");

        return callOther("sap_all_employee", "querySapEmployeeByWerks", jsonObject);
    }

    @RequestMapping(value = "batcheSyncSingleEmployee")
    @CatchErr
    public ResultMsg<String> batcheSyncSingleEmployee(@RequestBody List<JSONObject> list) {
        ResultMsg<String> result = new ResultMsg<>();

        try {
            List<String> errorMessages = new ArrayList<>(); // 用于存储错误信息

            CompletableFuture<Void> allTasks = CompletableFuture.allOf(
                    list.stream()
                            .map(jsonObject -> CompletableFuture.runAsync(() -> {
                                String account = jsonObject.getString("account");
                                String companyCode = jsonObject.getString("companyCode");
                                String currentUserId = jsonObject.getString("currentUserId");
                                ResultMsg resultMsg = employeesync("account", companyCode, currentUserId, account);
                                if (!resultMsg.getIsOk()) {
                                    errorMessages.add(resultMsg.getMsg());
                                }
                            }, threadPoolTaskExecutor))
                            .toArray(CompletableFuture[]::new));

            allTasks.join();

            // 检查是否有任何错误
            if (errorMessages.isEmpty()) {
                result.setOk(true);
                result.setMsg("操作成功");
            } else {
                result.setOk(false);
                result.setMsg(String.join("；", errorMessages));
            }

            return result;
        } catch (Exception e) {
            log.error("未知错误: ", e);
            result.setOk(false);
            result.setMsg("未知错误，请联系管理员：" + e.getMessage());
            return result;
        }
    }

    @RequestMapping(value = "checkSingleEmployee")
    @CatchErr
    public ResultMsg<Boolean> checkSingleEmployee(@RequestParam String account, @RequestParam String companyCode) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        Boolean flag = sapEmployeeQueryService.checkSapEmployeeByAccount(account, companyCode);
        return getSuccessResult(flag);
    }

    @RequestMapping("/allEmployeeSync")
    @CatchErr
    public ResultMsg allEmployeeSync(@RequestParam String currentUserId) {
        return syncSapEmployeeScheduled.syncSapEmployee(currentUserId);
    }

    /**
     * 获取sap请求体
     */
    @PostMapping("/getSapRequestBody")
    @CatchErr
    public Object getSapRequestBody(@RequestBody JSONObject businessParams) {
        String option = businessParams.getString("option");
        QueryStrategy strategy = QueryStrategyFactory.getStrategy(option);
        List<JSONObject> jsonObjectList = strategy.buildSapParams(businessParams);
        IsmAppSetting appSetting = ismAppSettingService.getByCode(businessParams.getString("sysCode"));
        String appKey = appSetting.getAppKey2();

        JSONObject sapParams = jsonObjectList.get(0);
        try {
            return SapSignatureUtil.buildRequestParams(sapParams, appKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 接口被调用通用方法
     *
     * @param sysCode
     * @param methodName
     * @param params
     * @return
     */
    private ResultMsg beCall(String sysCode, String methodName, String params) {
        JSONObject resObj = ismService.callService(sysCode, methodName, JSONObject.parseObject(params));
        if ("success".equals(resObj.getString("flag"))) {
            return getSuccessResult(resObj.get("data"));
        } else {
            return getWarnResult(resObj.getString("msg"));
        }
    }

    @RequestMapping(value = "/reCall/materialNo", method = {RequestMethod.GET, RequestMethod.POST})
    @CatchErr("重新获取/更新SAP物料号失败")
    public ResultMsg reCallMaterialNo(@RequestParam Long logId) throws Exception {
        String res = ismService.reCallMaterialNo(logId);
        return "success".equals(res) ? getSuccessResult() : getWarnResult(res);
    }

    @RequestMapping(value = "/edit/materialNo", method = {RequestMethod.GET})
    @CatchErr("手动维护物料号失败")
    public ResultMsg editMaterialNo(@RequestParam Long logId) throws Exception {
        materialNoLogService.updateMaterialNo(logId);
        return getSuccessResult();
    }

    @RequestMapping(value = "/syncPartsSapNum", method = {RequestMethod.GET})
    @CatchErr("同步零件毛坯物料号失败（临时刷数据）")
    public ResultMsg syncPartsSapNum() throws Exception {
        ismSyncPartsSapNumService.syncPartsSapNum();
        return getSuccessResult();
    }
}
